﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

using Baza.EF.BLL;
using Baza.EF.DAL;
using System.Web.Security;

namespace Pep_3014_3070.Anonymous
{
    public partial class ApartmanDetails : System.Web.UI.Page
    {
        private Dictionary<int, List<ad_Customer_Get_Rate_By_ApartmanID_Result>> apartmani = new Dictionary<int, List<ad_Customer_Get_Rate_By_ApartmanID_Result>>();

        public Reservations rezervacija
        {
            get
            {
                if (Session["rezervacija"] == null)
                {
                    Session["rezervacija"] = new Reservations();
                }
                return (Reservations)Session["rezervacija"];
            }
            set
            {
                Session["rezercavija"] = value;
            }
        }
        protected int ApartmanID
        {
            get { return (int)ViewState["apartmanID"]; }
            set { ViewState["apartmanID"] = value; }
        }
        protected int OwnerID
        {
            get { return (int)ViewState["ownerID"]; }
            set { ViewState["ownerID"] = value; }
        }
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!IsPostBack)
            {
                ApartmanID = Convert.ToInt32(RouteData.Values["id"]);
                BindData();
            }
        }

        private void BindData()
        {
            //Pictures
            List<Pictures> temp = DAOwners.getPicturesByApartmanID(Convert.ToInt32(ApartmanID));

            ListView1.DataSource = temp;
            ListView2.DataSource = temp;
            ListView2.DataBind();
            ListView1.DataBind();

            //Apartman
            Apartments tempApart = new Apartments();
            tempApart = DACustomers.GetApartmanByID(Convert.ToInt32(ApartmanID));
            lblBathrooms.Text = tempApart.Bathrooms.ToString();
            lblBedrooms.Text = tempApart.Bedrooms.ToString();
            lblBeds.Text = tempApart.Beds.ToString();

            if (tempApart.Elevator == true)
                lblElevator.Text = "DA";
            else
                lblElevator.Text = "NE";
            lblFloor.Text = tempApart.Floor.ToString();
            lblToilets.Text = tempApart.Toilets.ToString();


            ad_Customer_Get_Ownet_By_ApartmanID_Result owner = DACustomers.getOwnerByApartmanID(ApartmanID);
            if (owner != null)
            {
                lblOwner.Text = owner.FirstName + " " + owner.LastName;
                lblType.Text = DACustomers.getApartmanTypeByApartmanID(ApartmanID);
                OwnerID = owner.OwnerID;

                lblAboutMe.Text = owner.AboutMe;
                OwnerHyperLink.NavigateUrl = "/Owner/" + owner.OwnerID;
                OwnerHyperLink.Text = owner.FirstName + " " + owner.LastName;
            }

            List<Descriptions> descList = DACustomers.GetDescriptions(Convert.ToInt32(ApartmanID));


            DescriptionRepeater.DataSource = descList;
            DescriptionRepeater.DataBind();


            //SIDE BAR

            CheckInInput.Text = string.Format("{0:m}", Convert.ToDateTime(rezervacija.CheckIn));
            CheckOutInput.Text = string.Format("{0:m}", Convert.ToDateTime(rezervacija.CheckOut));

            GuestDropDownList.SelectedIndex = Convert.ToInt32(rezervacija.NumberGuest);

            rezervacija.Price = getPrice(Convert.ToDateTime(rezervacija.CheckIn), Convert.ToDateTime(rezervacija.CheckOut),
                                        Convert.ToInt32(GuestDropDownList.SelectedIndex));

            lblPrice.Text = string.Format("{0:C}", rezervacija.Price);

            //Napraviti da se treze slicni proizvodi , najvise ocjenjenih apartmana . .  

            List<Apartments> preporuceniApartmani = GetSlicneApartmane(ApartmanID);
            PreporuceniRepeater.DataSource = preporuceniApartmani;
            PreporuceniRepeater.DataBind();

            if (preporuceniApartmani.Count != 0)
            {
                preporuka.Visible = true;

            }
            else
            {
                preporuka.Visible = false;

            }
        }

        private decimal getPrice(DateTime CheckIn, DateTime CheckOut, int NumberOfGuest)
        {
            int razlika = (CheckOut - CheckIn).Days;

            decimal price = Convert.ToDecimal(0);
            for (int j = 0; j < razlika; j++)
            {
                Prices tempPrice = new Prices();
                tempPrice = DACustomers.getPriceByApartmanID(ApartmanID, Convert.ToDateTime(CheckIn),
                                            (Convert.ToDateTime(CheckIn).AddDays(j + 1)));
                if (tempPrice != null)
                    price += Convert.ToDecimal(tempPrice.Price);
            }
            if (NumberOfGuest != 0)
                price *= Convert.ToInt32(GuestDropDownList.SelectedIndex);

            return price;
        }

        protected void btnRezerviraj_Click(object sender, EventArgs e)
        {

            DateTime cIn = Convert.ToDateTime(CheckInInput.Text);
            DateTime cOut = Convert.ToDateTime(CheckOutInput.Text);

            //provjera da li je datum ispravan . . . (postoji mogucnost da tik pred rezervaciju odustane od prvobitnog Termina. . .
            bool validData = DACustomers.CheckAvailability(ApartmanID, cIn, cOut);

            if (cIn.Date < DateTime.Now.Date)
            {
                AlertMessage("Datum dolaska ne moze biti u proslosti!");
                return;
            }
            if (cOut.Date <= DateTime.Now.Date)
            {
                AlertMessage("Datum odlaska ne smije biti u proslosti!");
                return;
            }

            if (validData == false)
            {
                AlertMessage("Odabrani termin rezervacije apartmana je ZAUZET");
                return;
            }

            if (Convert.ToInt32(GuestDropDownList.SelectedIndex) == 0)
            {
                AlertMessage("Odaberite broj gostiju!");
                return;
            }
            if (cIn < cOut && validData)
            {
                Rezerviraj();
            }
        }

        private void Rezerviraj()
        {
            rezervacija.CheckIn = Convert.ToDateTime(CheckInInput.Text);
            rezervacija.CheckOut = Convert.ToDateTime(CheckOutInput.Text);
            rezervacija.Price = getPrice(Convert.ToDateTime(CheckInInput.Text),
                Convert.ToDateTime(CheckOutInput.Text), Convert.ToInt32(GuestDropDownList.SelectedIndex));
            rezervacija.NumberGuest = Convert.ToInt32(GuestDropDownList.SelectedIndex);

            string url = string.Format("/Reservation/{0}", ApartmanID);
            if (url != "" || url != null)
            {

                Response.Redirect(url);
            }

        }

        private void ProvjeriVrijednosti()
        {

            DateTime cIn = Convert.ToDateTime(CheckInInput.Text);
            DateTime cOut = Convert.ToDateTime(CheckOutInput.Text);



            if (cIn.Date < cOut.Date && cIn.Date >= DateTime.Now.Date)
            {
                if (DACustomers.CheckAvailability(ApartmanID, cIn, cOut))
                {
                    decimal price = getPrice(cIn, cOut,
                                        Convert.ToInt32(GuestDropDownList.SelectedIndex));
                    if (Convert.ToInt32(GuestDropDownList.SelectedIndex) != 0)
                        price *= Convert.ToInt32(GuestDropDownList.SelectedIndex);
                    lblPrice.Text = price.ToString();
                }
            }
        }

        protected void GuestDropDownList_SelectedIndexChanged(object sender, EventArgs e)
        {
            ProvjeriVrijednosti();
        }
        private void AlertMessage(string errorMsg)
        {

            string message = "alert('" + errorMsg + "')";
            ScriptManager.RegisterClientScriptBlock(this.Page, this.GetType(), "alert", message, true);


        }


        #region Item-based preporuka

        public List<Apartments> GetSlicneApartmane(int apartmanID)
        {
            UcitajApartmane(apartmanID);
            List<ad_Customer_Get_Rate_By_ApartmanID_Result> ocjene = DACustomers.GetRateByApartmanId(apartmanID);


            List<ad_Customer_Get_Rate_By_ApartmanID_Result> zajednickeOcjene1 = new List<ad_Customer_Get_Rate_By_ApartmanID_Result>();
            List<ad_Customer_Get_Rate_By_ApartmanID_Result> zajednickeOcjene2 = new List<ad_Customer_Get_Rate_By_ApartmanID_Result>();

            List<Apartments> preporuceno = new List<Apartments>();

            //Prva petlja - lista svih proizvoda (ne uključujući onaj koji je proslijeđen u funkciju)
            foreach (var item in apartmani)
            {

                foreach (var o in ocjene)
                {
                    if (item.Value.Where(x => x.CustomerID == o.CustomerID).Count() > 0)
                    {
                        zajednickeOcjene1.Add(o);
                        zajednickeOcjene2.Add(item.Value.Where(x => x.CustomerID == o.CustomerID).First());

                    }
                }

                //Za računanje sličnosti se uzimaju samo zajedničke ocjene, odnosno ocjene istih klijenata/Customers-a za oba apartmana
                double slicnost = GetSlicnost(zajednickeOcjene1, zajednickeOcjene2);
                if (slicnost > 0.6) //Granična vrijednost (treshold)
                    preporuceno.Add(DACustomers.getApartmanByApartmanID(item.Key));

                zajednickeOcjene1.Clear();
                zajednickeOcjene2.Clear();
            }
            //Lista preporučenih Apartmana
            return preporuceno;
        }

        //Učitava se kolekcija proizvoda i njihovih ocjena (osim onog koji se trenutno pregleda)
        private void UcitajApartmane(int apartmanID)
        {
            List<ad_Customer_Ge_Active_Apartman_By_ApartmanID_Result> aktivniApartmani = new List<ad_Customer_Ge_Active_Apartman_By_ApartmanID_Result>();

            if (rezervacija.CheckIn != null && rezervacija.CheckOut != null)
                aktivniApartmani = DACustomers.getActiveApartman(apartmanID, Convert.ToDateTime(rezervacija.CheckIn),
                    Convert.ToDateTime(rezervacija.CheckOut));
            else
                aktivniApartmani = DACustomers.getActiveApartman(apartmanID, DateTime.Now, DateTime.Now.AddDays(7));

            List<ad_Customer_Get_Rate_By_ApartmanID_Result> ocjene = new List<ad_Customer_Get_Rate_By_ApartmanID_Result>();

            foreach (ad_Customer_Ge_Active_Apartman_By_ApartmanID_Result a in aktivniApartmani)
            {
                ocjene = DACustomers.GetRateByApartmanId(Convert.ToInt32(a.ApartmentID));

                if (ocjene.Count > 0)
                    apartmani.Add(Convert.ToInt32(a.ApartmentID), ocjene);

            }
        }

        //Cosine similarity
        private double GetSlicnost(List<ad_Customer_Get_Rate_By_ApartmanID_Result> ocjene1, List<ad_Customer_Get_Rate_By_ApartmanID_Result> ocjene2)
        {
            if (ocjene1.Count != ocjene2.Count)
                return 0;

            int brojnik = 0;
            double int1 = 0;
            double int2 = 0;

            for (int i = 0; i < ocjene1.Count; i++)
            {
                brojnik += Convert.ToInt32(ocjene1[i].Rate) * Convert.ToInt32(ocjene2[i].Rate);

                int1 += Convert.ToInt32(ocjene1[i].Rate * Convert.ToInt32(ocjene1[i].Rate));
                int2 += Convert.ToInt32(ocjene2[i].Rate * Convert.ToInt32(ocjene2[i].Rate));
            }

            int1 = Math.Sqrt(int1);
            int2 = Math.Sqrt(int2);

            double nazivnik = int1 * int2;

            if (nazivnik != 0)
                return brojnik / nazivnik;

            return 0;

        }

        #endregion


    }
}